package com.yhy.wxzn.wcs.device.rgv;

import cn.hutool.core.collection.CollUtil;
import com.yhy.wxzn.common.utils.SpringUtil;
import com.yhy.wxzn.common.utils.WcsUtils;
import com.yhy.wxzn.wcs.device.rgv.bean.Coord;
import com.yhy.wxzn.wcs.device.rgv.bean.FourWayRgv;
import com.yhy.wxzn.wcs.SystemInit;
import com.yhy.wxzn.wcs.device.rgv.bean.Lifter;
import com.yhy.wxzn.wcs.device.rgv.bean.Node;
import com.yhy.wxzn.wcs.entity.WcsTask;
import com.yhy.wxzn.wcs.service.impl.WcsMapInfoServiceImpl;
import com.yhy.wxzn.wcs.service.impl.WcsTaskServiceImpl;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

import static com.yhy.wxzn.wcs.device.rgv.enums.RgvProgress.ASSIGNED_TO_RGV;

/**
 * RGV任务分配
 * 1.层优先原则，当前层有车，则任务给当前层车辆，当前层无车，则分配给临近层车辆
 * 2.就绪优先原则，定时10分钟，自动重新分配故障测量的未执行任务，错误任务不进行重新分配
 * 3.层均衡原则，定时10分钟库内未执行任务，重新均衡车辆，仅就绪车辆
 */
@Slf4j
public class RgvTaskAssignManagerThread extends Thread{

     private WcsTaskServiceImpl taskService = SpringUtil.getBean(WcsTaskServiceImpl.class);
     private WcsMapInfoServiceImpl mapInfoService = SpringUtil.getBean(WcsMapInfoServiceImpl.class);

     private int wareHoseLayerNum;


     public RgvTaskAssignManagerThread(){
         this.wareHoseLayerNum = mapInfoService.maxZ();
     }




    @Override
    public void run() {
        while (true){
            try {
                WcsUtils.sleep(1000);
                process();
            }catch (Exception e){
                log.error(e.getMessage(),e);
            }
        }
    }

    private void process() {
        List<WcsTask> unAssignTasks = taskService.getUnAssignTask();

        Map<Integer, List<WcsTask>> layerToTasks = unAssignTasks.stream().collect(Collectors.groupingBy(task -> Node.parseCoord(task.getEnd()).getZ()));

        Map<Integer, List<FourWayRgv>> layerToRgvs = SystemInit.fourWayRgvs.stream().collect(Collectors.groupingBy(
                rgv -> {
                    int layer = 0;
                    try {
                        Node location = rgv.getCurLocation();
                        layer = location.getZ();
                    } catch (Exception e) { }
                    return layer;
                }
        ));

        layerPriorityPrinciple(layerToTasks, layerToRgvs);
    }




    private void layerPriorityPrinciple(Map<Integer, List<WcsTask>> layerToTasks, Map<Integer, List<FourWayRgv>> layerToRgvs) {
        for (Map.Entry<Integer, List<WcsTask>> entry : layerToTasks.entrySet()) {
            Integer layer = entry.getKey();
            List<WcsTask> tasks = entry.getValue();
            List<FourWayRgv> fourWayRgvs;
            int i = layer;
            int j = layer;
            while (true){
                if (i > wareHoseLayerNum || j < 1) return;
                if (CollUtil.isNotEmpty(fourWayRgvs = layerToRgvs.get(i++)))  break;
                if (CollUtil.isNotEmpty(fourWayRgvs = layerToRgvs.get(j--)))  break;
            }
            for (WcsTask task : tasks) {
                Random random = new Random();
                FourWayRgv rgv = fourWayRgvs.get(random.nextInt(fourWayRgvs.size()));
                // todo 原子性
                taskService.assignTask(task.getTaskId(),rgv.getDeviceInfo().getId());
                taskService.updateRgvProgressReturnBoole(task,ASSIGNED_TO_RGV);
            }
        }
        return;
    }


}
